<!DOCTYPE HTML>
<!--
	Dimension by HTML5 UP
	html5up.net | @ajlkn
	Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
 <head>
  <title>
   Dimension by HTML5 UP
  </title>
  <!-- <meta charset="utf-8" /> -->
  <!-- <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> -->
  <meta charset="utf-8"/>
  <meta content="width=device-width,initial-scale=1.0" name="viewport"/>
  <link href="../../assets/css/article.css" rel="stylesheet"/>
  <link href="https://cdn.bootcss.com/highlight.js/9.15.8/styles/github.min.css" rel="stylesheet"/>
  <noscript>
   <link href="../../assets/css/noscript.css" rel="stylesheet"/>
  </noscript>
 </head>
 <body>
  <div id="app">
  </div>
  <!-- built files will be auto injected -->
 </body>
 <body class="is-preload">
  <!-- Wrapper -->
  <div id="wrapper">
   <!-- Main -->
   <div id="main">
    <article id="article">
     <h1 id="shardingsphere-logicsql">
      ShardingSphere LogicSQL 的生成探索
     </h1>
     <hr/>
     <h2 id="_1">
      简介
     </h2>
     <p>
      在上两篇文中，我们探索了SQLToken和真实SQL的生成的想关代码，本文继续来探索最开始的一个LogicSQL的生成，补全这一块拼图
     </p>
     <h2 id="_2">
      源码探索
     </h2>
     <p>
      继续上面两篇的探索：
     </p>
     <ul>
      <li>
       <a href="https://juejin.cn/post/7003073129643769869">
        ShardingSphere 语句解析生成初探
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/7003899320357355550">
        ShardingSphere SQLToken 生成探索
       </a>
      </li>
     </ul>
     <p>
      其中生成真实的SQL有两个要素：
     </p>
     <ul>
      <li>
       逻辑表名到真实表名的映射：这个在SQLToken生成的
      </li>
      <li>
       拼接SQL语句时，对应的index位置，这个目前看来是在LogicSQL中就生成好了的
      </li>
     </ul>
     <p>
      目前就还差index生成的东西，我们接下来就看看LogicSQL的相关代码：
     </p>
     <h3 id="_3">
      寻找切入点
     </h3>
     <p>
      下面是LogicSQL的生成部分：
     </p>
     <div class="codehilite">
      <pre><span></span><code>    <span class="kd">private</span> <span class="n">ExecutionContext</span> <span class="nf">createExecutionContext</span><span class="p">()</span> <span class="p">{</span>
        <span class="n">LogicSQL</span> <span class="n">logicSQL</span> <span class="o">=</span> <span class="n">createLogicSQL</span><span class="p">();</span>
        <span class="n">SQLCheckEngine</span><span class="p">.</span><span class="na">check</span><span class="p">(</span><span class="n">logicSQL</span><span class="p">.</span><span class="na">getSqlStatementContext</span><span class="p">().</span><span class="na">getSqlStatement</span><span class="p">(),</span> <span class="n">logicSQL</span><span class="p">.</span><span class="na">getParameters</span><span class="p">(),</span> 
                <span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getMetaData</span><span class="p">(</span><span class="n">connection</span><span class="p">.</span><span class="na">getSchemaName</span><span class="p">()).</span><span class="na">getRuleMetaData</span><span class="p">().</span><span class="na">getRules</span><span class="p">(),</span> <span class="n">connection</span><span class="p">.</span><span class="na">getSchemaName</span><span class="p">(),</span> <span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getMetaDataMap</span><span class="p">(),</span> <span class="kc">null</span><span class="p">);</span>
        <span class="n">ExecutionContext</span> <span class="n">result</span> <span class="o">=</span> <span class="n">kernelProcessor</span><span class="p">.</span><span class="na">generateExecutionContext</span><span class="p">(</span><span class="n">logicSQL</span><span class="p">,</span> <span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getMetaData</span><span class="p">(</span><span class="n">connection</span><span class="p">.</span><span class="na">getSchemaName</span><span class="p">()),</span> <span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getProps</span><span class="p">());</span>
        <span class="n">findGeneratedKey</span><span class="p">(</span><span class="n">result</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">generatedKey</span> <span class="o">-&gt;</span> <span class="n">generatedValues</span><span class="p">.</span><span class="na">addAll</span><span class="p">(</span><span class="n">generatedKey</span><span class="p">.</span><span class="na">getGeneratedValues</span><span class="p">()));</span>
        <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kd">private</span> <span class="n">LogicSQL</span> <span class="nf">createLogicSQL</span><span class="p">()</span> <span class="p">{</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">Object</span><span class="o">&gt;</span> <span class="n">parameters</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o">&lt;&gt;</span><span class="p">(</span><span class="n">getParameters</span><span class="p">());</span>
        <span class="n">SQLStatementContext</span><span class="o">&lt;?&gt;</span> <span class="n">sqlStatementContext</span> <span class="o">=</span> <span class="n">SQLStatementContextFactory</span><span class="p">.</span><span class="na">newInstance</span><span class="p">(</span><span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getMetaDataMap</span><span class="p">(),</span> <span class="n">parameters</span><span class="p">,</span> <span class="n">sqlStatement</span><span class="p">,</span> <span class="n">connection</span><span class="p">.</span><span class="na">getSchemaName</span><span class="p">());</span>
        <span class="k">return</span> <span class="k">new</span> <span class="n">LogicSQL</span><span class="p">(</span><span class="n">sqlStatementContext</span><span class="p">,</span> <span class="n">sql</span><span class="p">,</span> <span class="n">parameters</span><span class="p">);</span>
    <span class="p">}</span>
</code></pre>
     </div>
     <p>
      但通过debug看到相关的东西其实之前就生成好了：
     </p>
     <p>
      <img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c845fff594d84e0794eca5a379f0ee72~tplv-k3u1fbpfcp-watermark.image"/>
     </p>
     <p>
      其中的preparedStatement就有了相关的index信息，看来是在某一步就初始化好了的，我们找到对应的初始化语句，如下：
     </p>
     <div class="codehilite">
      <pre><span></span><code><span class="err">#</span> <span class="n">ShardingSpherePreparedStatement</span><span class="p">.</span><span class="na">java</span>
    <span class="kd">private</span> <span class="nf">ShardingSpherePreparedStatement</span><span class="p">(</span><span class="kd">final</span> <span class="n">ShardingSphereConnection</span> <span class="n">connection</span><span class="p">,</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">sql</span><span class="p">,</span>
                                            <span class="kd">final</span> <span class="kt">int</span> <span class="n">resultSetType</span><span class="p">,</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">resultSetConcurrency</span><span class="p">,</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">resultSetHoldability</span><span class="p">,</span> <span class="kd">final</span> <span class="kt">boolean</span> <span class="n">returnGeneratedKeys</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">SQLException</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">Strings</span><span class="p">.</span><span class="na">isNullOrEmpty</span><span class="p">(</span><span class="n">sql</span><span class="p">))</span> <span class="p">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="n">SQLException</span><span class="p">(</span><span class="n">SQLExceptionConstant</span><span class="p">.</span><span class="na">SQL_STRING_NULL_OR_EMPTY</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">this</span><span class="p">.</span><span class="na">connection</span> <span class="o">=</span> <span class="n">connection</span><span class="p">;</span>
        <span class="n">metaDataContexts</span> <span class="o">=</span> <span class="n">connection</span><span class="p">.</span><span class="na">getContextManager</span><span class="p">().</span><span class="na">getMetaDataContexts</span><span class="p">();</span>
        <span class="k">this</span><span class="p">.</span><span class="na">sql</span> <span class="o">=</span> <span class="n">sql</span><span class="p">;</span>
        <span class="n">statements</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o">&lt;&gt;</span><span class="p">();</span>
        <span class="n">parameterSets</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o">&lt;&gt;</span><span class="p">();</span>
        <span class="n">ShardingSphereSQLParserEngine</span> <span class="n">sqlParserEngine</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ShardingSphereSQLParserEngine</span><span class="p">(</span>
                <span class="n">DatabaseTypeRegistry</span><span class="p">.</span><span class="na">getTrunkDatabaseTypeName</span><span class="p">(</span><span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getMetaData</span><span class="p">(</span><span class="n">connection</span><span class="p">.</span><span class="na">getSchemaName</span><span class="p">()).</span><span class="na">getResource</span><span class="p">().</span><span class="na">getDatabaseType</span><span class="p">()));</span>
    <span class="c1">// 这里进行生成的</span>
        <span class="n">sqlStatement</span> <span class="o">=</span> <span class="n">sqlParserEngine</span><span class="p">.</span><span class="na">parse</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
        <span class="n">parameterMetaData</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ShardingSphereParameterMetaData</span><span class="p">(</span><span class="n">sqlStatement</span><span class="p">);</span>
        <span class="n">statementOption</span> <span class="o">=</span> <span class="n">returnGeneratedKeys</span> <span class="o">?</span> <span class="k">new</span> <span class="n">StatementOption</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">:</span> <span class="k">new</span> <span class="n">StatementOption</span><span class="p">(</span><span class="n">resultSetType</span><span class="p">,</span> <span class="n">resultSetConcurrency</span><span class="p">,</span> <span class="n">resultSetHoldability</span><span class="p">);</span>
        <span class="n">JDBCExecutor</span> <span class="n">jdbcExecutor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">JDBCExecutor</span><span class="p">(</span><span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getExecutorEngine</span><span class="p">(),</span> <span class="n">connection</span><span class="p">.</span><span class="na">isHoldTransaction</span><span class="p">());</span>
        <span class="n">driverJDBCExecutor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">DriverJDBCExecutor</span><span class="p">(</span><span class="n">connection</span><span class="p">.</span><span class="na">getSchemaName</span><span class="p">(),</span> <span class="n">metaDataContexts</span><span class="p">,</span> <span class="n">jdbcExecutor</span><span class="p">);</span>
        <span class="n">rawExecutor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">RawExecutor</span><span class="p">(</span><span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getExecutorEngine</span><span class="p">(),</span> <span class="n">connection</span><span class="p">.</span><span class="na">isHoldTransaction</span><span class="p">(),</span> <span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getProps</span><span class="p">());</span>
        <span class="c1">// TODO Consider FederateRawExecutor</span>
        <span class="n">federateExecutor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FederateJDBCExecutor</span><span class="p">(</span><span class="n">connection</span><span class="p">.</span><span class="na">getSchemaName</span><span class="p">(),</span> <span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getOptimizeContextFactory</span><span class="p">(),</span> <span class="n">metaDataContexts</span><span class="p">.</span><span class="na">getProps</span><span class="p">(),</span> <span class="n">jdbcExecutor</span><span class="p">);</span>
        <span class="n">batchPreparedStatementExecutor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">BatchPreparedStatementExecutor</span><span class="p">(</span><span class="n">metaDataContexts</span><span class="p">,</span> <span class="n">jdbcExecutor</span><span class="p">,</span> <span class="n">connection</span><span class="p">.</span><span class="na">getSchemaName</span><span class="p">());</span>
        <span class="n">kernelProcessor</span> <span class="o">=</span> <span class="k">new</span> <span class="n">KernelProcessor</span><span class="p">();</span>
    <span class="p">}</span>
</code></pre>
     </div>
     <p>
      我们再往前找找，看到是在OrderRepositoryImpl.java中进行触发的：
     </p>
     <div class="codehilite">
      <pre><span></span><code><span class="err">#</span> <span class="n">OrderRepositoryImpl</span><span class="p">.</span><span class="na">java</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">Long</span> <span class="nf">insert</span><span class="p">(</span><span class="kd">final</span> <span class="n">Order</span> <span class="n">order</span><span class="p">)</span> <span class="kd">throws</span> <span class="n">SQLException</span> <span class="p">{</span>
        <span class="n">String</span> <span class="n">sql</span> <span class="o">=</span> <span class="s">"INSERT INTO t_order (user_id, address_id, status) VALUES (?, ?, ?)"</span><span class="p">;</span>
        <span class="k">try</span> <span class="p">(</span><span class="n">Connection</span> <span class="n">connection</span> <span class="o">=</span> <span class="n">dataSource</span><span class="p">.</span><span class="na">getConnection</span><span class="p">();</span>
             <span class="n">PreparedStatement</span> <span class="n">preparedStatement</span> <span class="o">=</span> <span class="n">connection</span><span class="p">.</span><span class="na">prepareStatement</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">Statement</span><span class="p">.</span><span class="na">RETURN_GENERATED_KEYS</span><span class="p">))</span> <span class="p">{</span>
            <span class="n">preparedStatement</span><span class="p">.</span><span class="na">setInt</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">order</span><span class="p">.</span><span class="na">getUserId</span><span class="p">());</span>
            <span class="n">preparedStatement</span><span class="p">.</span><span class="na">setLong</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">order</span><span class="p">.</span><span class="na">getAddressId</span><span class="p">());</span>
            <span class="n">preparedStatement</span><span class="p">.</span><span class="na">setString</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">order</span><span class="p">.</span><span class="na">getStatus</span><span class="p">());</span>
            <span class="n">preparedStatement</span><span class="p">.</span><span class="na">executeUpdate</span><span class="p">();</span>
            <span class="k">try</span> <span class="p">(</span><span class="n">ResultSet</span> <span class="n">resultSet</span> <span class="o">=</span> <span class="n">preparedStatement</span><span class="p">.</span><span class="na">getGeneratedKeys</span><span class="p">())</span> <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">resultSet</span><span class="p">.</span><span class="na">next</span><span class="p">())</span> <span class="p">{</span>
                    <span class="n">order</span><span class="p">.</span><span class="na">setOrderId</span><span class="p">(</span><span class="n">resultSet</span><span class="p">.</span><span class="na">getLong</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">order</span><span class="p">.</span><span class="na">getOrderId</span><span class="p">();</span>
    <span class="p">}</span>
</code></pre>
     </div>
     <p>
      那我们就继续探索：sqlStatement = sqlParserEngine.parse(sql, true);
     </p>
     <p>
      我们一直跟着下去，来到一个SQL处理的相关类：MySQLStatementParser.java
     </p>
     <p>
      其给人的第一个感觉是相当的复杂，我们跟着debug下去，看到进入到相关的insert处理的分支
     </p>
     <div class="codehilite">
      <pre><span></span><code>            <span class="k">case</span> <span class="n">XA</span><span class="p">:</span>
                <span class="n">enterOuterAlt</span><span class="p">(</span><span class="n">_localctx</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
                <span class="p">{</span>
                <span class="n">setState</span><span class="p">(</span><span class="mi">1246</span><span class="p">);</span>
                <span class="n">_errHandler</span><span class="p">.</span><span class="na">sync</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
                <span class="k">switch</span> <span class="p">(</span> <span class="n">getInterpreter</span><span class="p">().</span><span class="na">adaptivePredict</span><span class="p">(</span><span class="n">_input</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">_ctx</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
                <span class="k">case</span> <span class="mi">1</span><span class="p">:</span>
                    <span class="p">{</span>
                    <span class="n">setState</span><span class="p">(</span><span class="mi">1146</span><span class="p">);</span>
                    <span class="n">select</span><span class="p">();</span>
                    <span class="p">}</span>
                    <span class="k">break</span><span class="p">;</span>
                <span class="k">case</span> <span class="mi">2</span><span class="p">:</span>
                    <span class="p">{</span>
                    <span class="n">setState</span><span class="p">(</span><span class="mi">1147</span><span class="p">);</span>
                    <span class="n">insert</span><span class="p">();</span>
                    <span class="p">}</span>
                    <span class="k">break</span><span class="p">;</span>
</code></pre>
     </div>
     <p>
      跟着下去，来到insert语句处理具体函数：
     </p>
     <div class="codehilite">
      <pre><span></span><code><span class="err">#</span> <span class="n">MySQLStatementParser</span><span class="p">.</span><span class="na">java</span>
    <span class="kd">public</span> <span class="kd">final</span> <span class="n">InsertContext</span> <span class="nf">insert</span><span class="p">()</span> <span class="kd">throws</span> <span class="n">RecognitionException</span> <span class="p">{</span>
        <span class="n">InsertContext</span> <span class="n">_localctx</span> <span class="o">=</span> <span class="k">new</span> <span class="n">InsertContext</span><span class="p">(</span><span class="n">_ctx</span><span class="p">,</span> <span class="n">getState</span><span class="p">());</span>
        <span class="n">enterRule</span><span class="p">(</span><span class="n">_localctx</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">RULE_insert</span><span class="p">);</span>
        <span class="kt">int</span> <span class="n">_la</span><span class="p">;</span>
        <span class="k">try</span> <span class="p">{</span>
            <span class="n">enterOuterAlt</span><span class="p">(</span><span class="n">_localctx</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
            <span class="p">{</span>
            <span class="n">setState</span><span class="p">(</span><span class="mi">1258</span><span class="p">);</span>
            <span class="c1">// Insert相关处理</span>
            <span class="n">match</span><span class="p">(</span><span class="n">INSERT</span><span class="p">);</span>
            <span class="n">setState</span><span class="p">(</span><span class="mi">1259</span><span class="p">);</span>
            <span class="n">insertSpecification</span><span class="p">();</span>
            <span class="n">setState</span><span class="p">(</span><span class="mi">1261</span><span class="p">);</span>
            <span class="n">_errHandler</span><span class="p">.</span><span class="na">sync</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
            <span class="n">_la</span> <span class="o">=</span> <span class="n">_input</span><span class="p">.</span><span class="na">LA</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">_la</span><span class="o">==</span><span class="n">INTO</span><span class="p">)</span> <span class="p">{</span>
                <span class="p">{</span>
                <span class="n">setState</span><span class="p">(</span><span class="mi">1260</span><span class="p">);</span>
                <span class="c1">// into 相关处理</span>
                <span class="n">match</span><span class="p">(</span><span class="n">INTO</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span>

            <span class="n">setState</span><span class="p">(</span><span class="mi">1263</span><span class="p">);</span>
            <span class="c1">// 表名相关处理</span>
            <span class="n">tableName</span><span class="p">();</span>
            <span class="n">setState</span><span class="p">(</span><span class="mi">1265</span><span class="p">);</span>
            <span class="n">_errHandler</span><span class="p">.</span><span class="na">sync</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
            <span class="n">_la</span> <span class="o">=</span> <span class="n">_input</span><span class="p">.</span><span class="na">LA</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">_la</span><span class="o">==</span><span class="n">PARTITION</span><span class="p">)</span> <span class="p">{</span>
                <span class="p">{</span>
                <span class="n">setState</span><span class="p">(</span><span class="mi">1264</span><span class="p">);</span>
                <span class="n">partitionNames</span><span class="p">();</span>
                <span class="p">}</span>
            <span class="p">}</span>

            <span class="n">setState</span><span class="p">(</span><span class="mi">1270</span><span class="p">);</span>
            <span class="n">_errHandler</span><span class="p">.</span><span class="na">sync</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
            <span class="k">switch</span> <span class="p">(</span> <span class="n">getInterpreter</span><span class="p">().</span><span class="na">adaptivePredict</span><span class="p">(</span><span class="n">_input</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="n">_ctx</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
            <span class="k">case</span> <span class="mi">1</span><span class="p">:</span>
                <span class="p">{</span>
                <span class="n">setState</span><span class="p">(</span><span class="mi">1267</span><span class="p">);</span>
                <span class="c1">// values相关处理</span>
                <span class="n">insertValuesClause</span><span class="p">();</span>
                <span class="p">}</span>
                <span class="k">break</span><span class="p">;</span>
            <span class="k">case</span> <span class="mi">2</span><span class="p">:</span>
                <span class="p">{</span>
                <span class="n">setState</span><span class="p">(</span><span class="mi">1268</span><span class="p">);</span>
                <span class="n">setAssignmentsClause</span><span class="p">();</span>
                <span class="p">}</span>
                <span class="k">break</span><span class="p">;</span>
            <span class="k">case</span> <span class="mi">3</span><span class="p">:</span>
                <span class="p">{</span>
                <span class="n">setState</span><span class="p">(</span><span class="mi">1269</span><span class="p">);</span>
                <span class="n">insertSelectClause</span><span class="p">();</span>
                <span class="p">}</span>
                <span class="k">break</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="n">setState</span><span class="p">(</span><span class="mi">1273</span><span class="p">);</span>
            <span class="n">_errHandler</span><span class="p">.</span><span class="na">sync</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
            <span class="n">_la</span> <span class="o">=</span> <span class="n">_input</span><span class="p">.</span><span class="na">LA</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">_la</span><span class="o">==</span><span class="n">ON</span><span class="p">)</span> <span class="p">{</span>
                <span class="p">{</span>
                <span class="n">setState</span><span class="p">(</span><span class="mi">1272</span><span class="p">);</span>
                <span class="n">onDuplicateKeyClause</span><span class="p">();</span>
                <span class="p">}</span>
            <span class="p">}</span>

            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">catch</span> <span class="p">(</span><span class="n">RecognitionException</span> <span class="n">re</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">_localctx</span><span class="p">.</span><span class="na">exception</span> <span class="o">=</span> <span class="n">re</span><span class="p">;</span>
            <span class="n">_errHandler</span><span class="p">.</span><span class="na">reportError</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="n">re</span><span class="p">);</span>
            <span class="n">_errHandler</span><span class="p">.</span><span class="na">recover</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="n">re</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">finally</span> <span class="p">{</span>
            <span class="n">exitRule</span><span class="p">();</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">_localctx</span><span class="p">;</span>
    <span class="p">}</span>
</code></pre>
     </div>
     <p>
      在上面的函数中，我们大意看到几个比较关键的处理函数：
     </p>
     <ul>
      <li>
       Insert相关处理 : match(INSERT);
      </li>
      <li>
       into 相关处理 : match(INTO);
      </li>
      <li>
       表名相关处理 : tableName();
      </li>
      <li>
       values相关处理 : insertValuesClause();
      </li>
     </ul>
     <p>
      其规则跟下来有点复杂了，有循环和嵌套处理的，目前是梳理不清楚了
     </p>
     <p>
      但其大意都是得到对应的开始和结束位置之类的，如下图：
     </p>
     <p>
      <img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ac52f5a21f2d492886920699ba13e52f~tplv-k3u1fbpfcp-watermark.image"/>
     </p>
     <p>
      最终得到结果如下：
     </p>
     <p>
      <img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6fadbe3480fc463cb706d50dc62758c6~tplv-k3u1fbpfcp-watermark.image"/>
     </p>
     <p>
      到结果后，相关的返回函数如下：
     </p>
     <div class="codehilite">
      <pre><span></span><code><span class="nd">@RequiredArgsConstructor</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">SQLParserExecutor</span> <span class="p">{</span>

    <span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">databaseType</span><span class="p">;</span>

    <span class="cm">/**</span>
<span class="cm">     * Parse SQL.</span>
<span class="cm">     * </span>
<span class="cm">     * @param sql SQL to be parsed</span>
<span class="cm">     * @return parse tree</span>
<span class="cm">     */</span>
    <span class="kd">public</span> <span class="n">ParseTree</span> <span class="nf">parse</span><span class="p">(</span><span class="kd">final</span> <span class="n">String</span> <span class="n">sql</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ParseASTNode</span> <span class="n">result</span> <span class="o">=</span> <span class="n">twoPhaseParse</span><span class="p">(</span><span class="n">sql</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="na">getRootNode</span><span class="p">()</span> <span class="k">instanceof</span> <span class="n">ErrorNode</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="n">SQLParsingException</span><span class="p">(</span><span class="s">"Unsupported SQL of `%s`"</span><span class="p">,</span> <span class="n">sql</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">result</span><span class="p">.</span><span class="na">getRootNode</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
     </div>
     <p>
      result.getRootNode() 如下：
     </p>
     <div class="codehilite">
      <pre><span></span><code><span class="nd">@RequiredArgsConstructor</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">ParseASTNode</span> <span class="kd">implements</span> <span class="n">ASTNode</span> <span class="p">{</span>

    <span class="kd">private</span> <span class="kd">final</span> <span class="n">ParseTree</span> <span class="n">parseTree</span><span class="p">;</span>

    <span class="cm">/**</span>
<span class="cm">     * Get root node.</span>
<span class="cm">     * </span>
<span class="cm">     * @return root node</span>
<span class="cm">     */</span>
    <span class="kd">public</span> <span class="n">ParseTree</span> <span class="nf">getRootNode</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">parseTree</span><span class="p">.</span><span class="na">getChild</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
     </div>
     <p>
      而result的结果如下图，getChild（0）就是得到上面我们Insert解析后得到的结果
     </p>
     <p>
      <img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/90ef010f18ac49fa836afa9dd67c0433~tplv-k3u1fbpfcp-watermark.image"/>
     </p>
     <h2 id="_4">
      总结
     </h2>
     <p>
      感觉看的迷迷糊糊的，很多地方目前还不能很好的理解
     </p>
     <p>
      但我们起码通过本次的探索知道了真实SQL的关键路径：
     </p>
     <ul>
      <li>
       通过原始的LogicSQL语句，经过的ShardingSphere的语法树解析，得到对应的各个部分的元数据，如开始和结束index
      </li>
      <li>
       根据语法树解析结果，得到对应的SQLToken，其中包含了如分库分表中的逻辑表到真实表的映射等关键信息
      </li>
      <li>
       根据SQLToken生成真实的SQL
      </li>
     </ul>
    </article>
   </div>
   <!-- Footer -->
   <footer id="footer">
    <p class="copyright">
     © Untitled. Design:
     <a href="https://html5up.net">
      HTML5 UP
     </a>
     .
    </p>
   </footer>
  </div>
  <!-- BG -->
  <div id="bg">
  </div>
  <!-- Scripts -->
  <script src="../assets/js/jquery.min.js">
  </script>
  <script src="../assets/js/browser.min.js">
  </script>
  <script src="../assets/js/breakpoints.min.js">
  </script>
  <script src="../assets/js/util.js">
  </script>
  <script src="../assets/js/main.js">
  </script>
 </body>
</html>
